package com.zyy.game.tianlong.network;

import com.alibaba.fastjson.JSON;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.zyy.game.tianlong.network.exception.ServiceException;
import com.zyy.game.tianlong.vo.ResultVo;
import lombok.AllArgsConstructor;
import org.springframework.util.StringUtils;

/**
 * 事件方法对象
 *
 * @author relufi
 * @date 2019/7/24 0024
 */
@AllArgsConstructor
class HandlerMethod {
    private final Object bean;
    private final MethodAccess methodAccess;
    private final int methodIndex;
    private final Integer contextIndex;
    private final int paramCount;
    private final Integer dataIndex;
    private final Class<?> dataClass;
    private final int moduleCode;
    private final int eventCode;
    private final boolean defaultSuccess;
    private final boolean defaultResult;

    /**
     * 运行事件方法
     *
     * @param ctx 连接处理器上下文
     * @param msg 数据
     */
    void invoke(GameContext ctx, SocketMsg msg) {
        Object[] params = new Object[paramCount];
        if (contextIndex != null) {
            params[contextIndex] = ctx;
        }
        if (dataIndex != null) {
            String msgData = msg.getData();
            Object data;
            if (StringUtils.isEmpty(msgData)) {
                data = null;
            } else if (dataClass == String.class) {
                data = msgData;
            } else {
                data = JSON.parseObject(msgData, dataClass);
            }
            params[dataIndex] = data;
        }
        ctx.setOpenCode(moduleCode == -1 ? msg.getOpCode() : moduleCode);
        ctx.setSubCode(eventCode == -1 ? msg.getSubCode() : eventCode);
        try {
            methodAccess.invoke(bean, methodIndex, params);
            if (defaultSuccess) {
                ctx.writeAndFlush(ResultVo.success());
            }
        } catch (ServiceException e) {
            if (defaultResult) {
                ctx.writeAndFlush(ResultVo.error(e));
            } else {
                throw e;
            }
        }
    }
}
